package com.yangjian.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yangjian.bean.Category;
import com.yangjian.bean.Dish;
import com.yangjian.bean.DishFlavor;

import com.yangjian.dao.CategoryDao;
import com.yangjian.dao.DishDao;
import com.yangjian.dao.DishFlavorDao;
import com.yangjian.dto.DishDto;
import com.yangjian.exception.CustomException;
import com.yangjian.page.PageParameter;
import com.yangjian.service.CategoryService;
import com.yangjian.service.DishFlavorService;
import com.yangjian.service.DishService;
import com.yangjian.util.BaseContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Transactional
@Service
public class DishServiceImpl implements DishService {


    @Autowired
    private DishDao dao;

    //@Autowired
    //private DishFlavorDao dishFlavorDao;

    @Lazy
    @Autowired
    private CategoryService categoryService;

    @Lazy
    @Autowired
    private DishFlavorService dishFlavorService;

    //注入redis对象
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据分类管理的id来查询菜品表
     *
     * @param cid
     * @return
     */
    @Cacheable(value = "dish",key = "#cid")
    @Override
    public List<Dish> findByCid(Long cid) {

        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Dish::getCategoryId, cid);
        List<Dish> dishes = dao.selectList(lqw);
        return dishes;
    }

    /**
     * 添加菜单的菜
     *
     * @param dishDto
     * @return
     */
   @CacheEvict(value = "dish",allEntries = true)
    @Override
    public int add(DishDto dishDto) {
        //添加菜单的菜品
        int row = dao.insert(dishDto);


        //判断添加菜品成功没，与口味存不存在，如果都成功就执行添加口味的操作
        if (row > 0 && dishDto.getFlavors().size() > 0) {
            int row1 = 0;

            for (DishFlavor flavor : dishDto.getFlavors()) {
                //设置Dish_id值
                flavor.setDishId(dishDto.getId());
                //添加口味
                // row1 += dishFlavorDao.insert(flavor);
                row1 += dishFlavorService.add(flavor);


            }
            return row1 == dishDto.getFlavors().size() ? 1 : 0;
        }


        return row;
    }

    /**
     * 分页查询菜单表
     *
     * @param page
     * @return
     */
    @Override

    public IPage<DishDto> findPage(PageParameter page) {
        //构建查询对象
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        //添加查询约束条件--名字
        lqw.like(page.getName() != null, Dish::getName, page.getName());

        //设置查询多少页，每页多少条
        IPage<Dish> page1 = new Page<>(page.getPage(), page.getPageSize());
        //调用dao进行分页查询
        IPage<Dish> page2 = dao.selectPage(page1, lqw);

        ////构建一个list集合,泛型为dishDto,用来存储dishDto对象
        //List<DishDto> list = new ArrayList<>();
        ////把查询到的集合数据拿出来
        //List<Dish> records = page2.getRecords();
        //
        ////遍历集合,取出每一个dish对象数据
        //for (Dish dish : records) {
        //    //遍历一次集合,就创建一次dishDto对象
        //    DishDto dishDto = new DishDto();
        //    //将dish身上的属性拷贝到dishDto中
        //    BeanUtils.copyProperties(dish, dishDto);
        //    //拿着菜品的分类id去分类表找对应的数据
        //    Category category = categoryDao.selectById(dish.getCategoryId());
        //    //把分类得到的name属性设置给dishDto
        //    dishDto.setCategoryName(category.getName());
        //
        //    //拿着菜单的口味id去菜单口味表找对应的数据
        //    List<DishFlavor> dishFlavors = dishFlavorService.findByDishId(dish.getId());
        //
        //    //把分类得到的dishFlavors属性设置给dishDto
        //    dishDto.setFlavors(dishFlavors);
        //
        //    //把构建好的每一个dishDto装到一个集合里
        //
        //    list.add(dishDto);
        //}


        //---------------------------使用流来包装数据----------------------------
        //使用流来遍历集合
        List<DishDto> dishDtoList = page2.getRecords().stream().map((dish) -> {

            //用菜品的dishID查询分类
            Category category = categoryService.findById(dish.getCategoryId());
            //查询口味
            List<DishFlavor> list = dishFlavorService.findByDishId(dish.getId());
            //把口味，菜品，分类组装到distDto类中
            //新建一个dishDto
            DishDto dishDto = new DishDto();
            //把分类的名字装进去
            dishDto.setCategoryName(category.getName());
            //把口味装进去
            dishDto.setFlavors(list);
            //把菜品拷贝到里面去
            BeanUtils.copyProperties(dish, dishDto);

            //返回dishDto
            return dishDto;

            //将每个dishDto添加到list集合里
        }).collect(Collectors.toList());

        //在循环外重新构建一个page对象
        IPage<DishDto> page3 = new Page<>();

        //往page对象里添加总记录数和当前条数数据
        page3.setTotal(page2.getTotal());
        page3.setRecords(dishDtoList);

        return page3;
    }

    /**
     * 修改菜单的菜
     *
     * @param dishDto
     * @return
     */
    @Override
    public int update(DishDto dishDto) {

        //首先更新自己的菜品（根据id修改）
        int row = dao.updateById(dishDto);

        //获取口味数据，判断口味数据有没有
        List<DishFlavor> flavors = dishDto.getFlavors();
        if (flavors != null && flavors.size() > 0) {
            //第一步删除口味数据
            int row2 = dishFlavorService.delete(dishDto.getId());
            //添加口味数据
            int row3 = 0;
            //遍历得到每一个口味
            for (DishFlavor flavor : flavors) {
                //设置口味表的dishId
                flavor.setDishId(dishDto.getId());
                //调用口味表的service，执行添加口味
                row3 += dishFlavorService.add(flavor);
            }
            //如果累加的数量等于口味集合的长度，如果相等就返回1，不相等返回0；
            return row3 == flavors.size() ? 1 : 0;
        }

        return row;
    }

    /**
     * 根据分类id来查菜品
     *
     * @param categoryId
     * @return
     */
    @Override
    public List<DishDto> findByCategoryId(long categoryId,Integer status) {
        //查询redis缓冲区

        String DishDto = (String) redisTemplate.opsForValue().get("dish_" + categoryId + "-" + status);
        //判断redis是否有，如果就就直接返回，没有就就查询数据库
       if (StringUtils.isNotEmpty(DishDto)){
           return JSON.parseObject(DishDto, List.class);
       }

        //构建条件对象
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        //设置条件
        lqw.eq(Dish::getCategoryId, categoryId);
        lqw.eq(status!=null,Dish::getStatus,status);
        //查询
        List<Dish> dishes = dao.selectList(lqw);
        List<DishDto> dishDtoList=dishes.stream().map(dish -> {
            //根据菜品id获取菜品口味
            List<DishFlavor> flavors = dishFlavorService.findByDishId(dish.getId());

            //创建dishDto对象
            DishDto dishDto = new DishDto();
            //把口味封装进去
            dishDto.setFlavors(flavors);
            //把菜品拷贝进去
            BeanUtils.copyProperties(dish,dishDto);
            return dishDto;
        }).collect(Collectors.toList());

        //把数据添加到redis缓存数据中
        String k="dish_" + categoryId + "-" + status;
        redisTemplate.opsForValue().set(k,JSON.toJSONString(dishDtoList),24, TimeUnit.HOURS);

        return dishDtoList;
    }

    /**
     * 修改菜品的起售停售状态
     *
     * @param status
     * @param ids
     * @return
     */
    @Override
    public int updateStatus(int status, List<Long> ids) {


        //根据菜品id集合查询得到所有的菜品
        List<Dish> list = dao.selectBatchIds(ids);

        int row = 0;
        //遍历得到每一个菜品
        for (Dish dish : list) {
            if (dish != null) {
                //修改菜品的状态
                dish.setStatus(status);
                //调用dao的根据id修改
                row = dao.updateById(dish);
            }
        }

        return row;
    }

    /**
     * 根据id删除（包含批量删除）
     *
     * @param ids
     * @return
     */
    @Override
    public int delete(List<Long> ids) {
        //删除菜品之前需要判断是否在起售状态，如果是就不能删除
        //构建条件对象
        LambdaQueryWrapper<Dish> lqw = new LambdaQueryWrapper<>();
        //设置条件
        lqw.eq(Dish::getStatus, 1);
        lqw.in(Dish::getId, ids);
        //查询有没有位于起售的
        Integer count = dao.selectCount(lqw);
        if (count>0){
            throw new CustomException("菜品位于起售状态，禁止删除！！");
        }
        //没有起售状态的话，就删除菜品
        int row = dao.deleteBatchIds(ids);
        //判断菜品是否删除成功
        if (row>0){
            for (Long id : ids) {
                //根据菜品id去删除菜品口味
                dishFlavorService.delete(id);
            }
        }

        return row;
    }

}
